/*
 * Inventory.java
 * Team qq 2011
 */
package com.google.code.timetrail.backend;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * This class provides an object to simulate and inventory and does things like
 * adding and subtracting items from the inventory
 * 
 * @author Anurrag
 * @version 1.01 Removed magic numbers and made it so that inventories get
 *          instantiated as empty and are filled in based on what Persons do
 * 
 * 
 */
public class Inventory implements Serializable {
	/** Inventory's SerialVersion ID, to be changed when the object is changed **/
	private static final long serialVersionUID = 20L;

	/**
	 * engines - instance of the engine held within the inventory
	 */
	private final Item engines;

	/**
	 * fCapacitors - instance of the FluxCapacitors held within the inventory.
	 */
	private final Item fCapacitors;

	/**
	 * hullParts - instance of HullPart to be held within the inventory.
	 */
	private final Item hullParts;

	/**
	 * food - instance of the Item Food to be held within inventory.
	 */
	private final Item food;

	/**
	 * fuelCells - instance of the Item FuelCell to be held within inventory.
	 */
	private final Item fuelCells;

	/**
	 * money - instance of the Item money that holds the players money in the
	 * inventory.
	 */
	private final Item money;

	/**
	 * timeBulletBills - instance of the Item TimeBulletBill that acts as
	 * ammunition.
	 */
	private final Item timeBulletBills;

	/**
	 * timeSuits - instance of the Item TimeSuit that acts as clothing in the
	 * inventory.
	 */
	private final Item timeSuits;

	/**
	 * INV_CAPACITY - the maximum amount of weight a player can hold. (value is
	 * 3500)
	 */
	private static final int INV_CAPACITY = 3500;

	/**
	 * INV_MIN - the minimum amount of weight a player could hold. (value is 0)
	 */
	private static final int INV_MIN = 0;

	/**
	 * invWeight - the current weight held in the inventory.
	 */
	private int invWeight;

	/**
	 * A List of the items in the inventory
	 */
	private final List<Item> itemList;

	/** Limit of which random to return */
	private static final int RANDOMLIMIT = 4;
	
	/**
	 * Constructor for Inventory. Creates instances of all the items to be held
	 * in the inventory. Sets initial weight to zero.
	 */
	public Inventory() {
		itemList = new ArrayList<Item>();
		invWeight = 0;

		money = new Money();
		fuelCells = new FuelCell();
		food = new Food();
		hullParts = new HullPart();
		fCapacitors = new FluxCapacitor();
		engines = new Engine();
		timeSuits = new TimeSuit();
		timeBulletBills = new TimeBulletBill();
		itemList.add(fuelCells);
		itemList.add(hullParts);
		itemList.add(fCapacitors);
		itemList.add(engines);

		itemList.add(food);
		itemList.add(timeSuits);
		itemList.add(timeBulletBills);
		itemList.add(money);

	}

	/**
	 * adds an item to the inventory without dealing with things like "cost" and
	 * "money" things like weight and capacity will still affect it
	 * 
	 * @param amount
	 *            how many items to be received
	 * @param item
	 *            what kind of item to be received
	 */
	public void addItem(int amount, Item item) {
		final boolean addConfirm = item.canAddCurrentAmount(amount);
		final int weightCheck = item.getWeight() * amount;

		if (addConfirm && (invWeight + weightCheck) <= INV_CAPACITY
				&& (invWeight + weightCheck) >= INV_MIN) {
			invWeight += weightCheck;
			item.addCurrentAmount(amount);
		}

		else {
			return;
		}
	}

	/**
	 * DOES NOT ADD AN ITEM TO THE INVENTORY, but it does test if it's possible
	 * 
	 * @param amount
	 *            the amount of an item that you are trying to add to the
	 *            inventory
	 * @param item
	 *            the item you are trying to add to the inventory
	 * @return true if it's possible to add to the inventory, false if it isn't.
	 */
	public boolean canAddItem(int amount, Item item) {
		final boolean addConfirm = item.canAddCurrentAmount(amount);
		final int weightCheck = item.getWeight() * amount;

		return addConfirm && invWeight + weightCheck <= INV_CAPACITY
				&& invWeight + weightCheck >= INV_MIN;
	}

	/**
	 * remove an item from the inventory without dealing with money still
	 * refactors weight when removed this is basically a call to add item, but
	 * with a more intuitive name
	 * 
	 * @param amount
	 *            the amount of items to remove from the inventory
	 * @param item
	 *            the type of item to remove
	 */
	public void removeItem(int amount, Item item) {
		if (amount < 0) {
			return;
		} else {
			addItem((amount * -1), item);
		}
	}

	/**
	 * DOES NOT REMOVE ANYTHING FROM THE INVENTORY but does test if it's
	 * possible
	 * 
	 * @param amount
	 *            the amount of the item you want to remove
	 * @param item
	 *            the item you want to remove
	 * @return true if it's possible, false if it's not
	 */
	public boolean canRemoveItem(int amount, Item item) {
		if (amount < 0) {
			return false;
		} else {
			return canAddItem((amount * -1), item);
		}
	}

	/**
	 * returns the real weight of the inventory
	 * 
	 * @return the inventory's current weight
	 */
	public int getInvWeight() {
		return invWeight;
	}

	/**
	 * sets the inventory weight, if the weight would not work return false
	 * 
	 * @param invWeight
	 *            the weight to set the inventory to
	 */
	public void setInvWeight(int invWeight) {
		this.invWeight = invWeight;

	}

	/**
	 * returns the instance of Money the person has
	 * 
	 * @return the inventory's money
	 */
	public Item getMoney() {
		return money;
	}

	/**
	 * returns the fuel cells of the inventory.
	 * 
	 * @return the inventory's fuel cells
	 */
	public Item getFuelCells() {
		return fuelCells;
	}

	/**
	 * returns the inventory's food
	 * 
	 * @return the inventory's food
	 */
	public Item getFood() {
		return food;
	}

	/**
	 * returns the inventory's hull parts.
	 * 
	 * @return the inventory's hull parts
	 */
	public Item getHullParts() {
		return hullParts;
	}

	/**
	 * returns the flux capacitors of the inventory.
	 * 
	 * @return the inventory's flux capacitors
	 */
	public Item getFCapacitors() {
		return fCapacitors;
	}

	/**
	 * returns the engines of the inventory.
	 * 
	 * @return the inventory's engine
	 */
	public Item getEngines() {
		return engines;
	}

	/**
	 * returns the clothing of the inventory.
	 * 
	 * @return the Time Suits of the inventory
	 */
	public Item getTimeSuits() {
		return timeSuits;
	}

	/**
	 * returns the time bullet bills to the inventory.
	 * 
	 * @return the inventory's time bullet bills
	 */
	public Item getTimeBulletBills() {
		return timeBulletBills;
	}

	/**
	 * returns the inventory's maximum capacity
	 * 
	 * @return the inventory's maximum capacity
	 */
	public int getCapacity() {
		return INV_CAPACITY;
	}

	/**
	 * Gives the string representation of the inventory.
	 * 
	 * @return the string representation of the inventory
	 */
	public String toString() {

		return "Weight: " + invWeight + "\n " + money.toString() + ": "
				+ money.getCurrentAmount() + "\n " + fuelCells.toString()
				+ ": " + fuelCells.getCurrentAmount() + "\n " + food.toString()
				+ ": " + food.getCurrentAmount() + "\n " + hullParts.toString()
				+ ": " + hullParts.getCurrentAmount() + "\n "
				+ fCapacitors.toString() + ": "
				+ fCapacitors.getCurrentAmount() + "\n " + engines.toString()
				+ ": " + engines.getCurrentAmount() + "\n "
				+ timeSuits.toString() + ": " + timeSuits.getCurrentAmount()
				+ "\n " + timeBulletBills.toString() + ": "
				+ timeBulletBills.getCurrentAmount();

	}

	/**
	 * gives you an instance of a random item in the inventory
	 * 
	 * @return the random item
	 */
	public Item getRandomItem() {
		final Random rand = new Random();
		return itemList.get(rand.nextInt(itemList.size()));
	}

	/**
	 * Gets you the random item but never the end
	 * 
	 * @return the random item
	 */
	public Item getRandomItemNotMoney() {
		final Random rand = new Random();
		return itemList.get(rand.nextInt(itemList.size() - 1));
	}

	/**
	 * Gives a random item from the item list, from items 0 to 3 which correlate
	 * to fuelCells, hullParts, fCapacitors, and engines
	 * 
	 * @return a random item dealing with the ship.
	 */
	public Item getRandomShipItem() {
		final Random rand = new Random();
		return itemList.get(rand.nextInt(RANDOMLIMIT));

	}

}
